Pass --cap-lints=allow instead of -Awarnings
authorAlex Crichton <alex@alexcrichton.com>
Fri, 24 Jul 2015 18:49:19 +0000 (11:49 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 24 Jul 2015 21:13:30 +0000 (14:13 -0700)
This commit adds support to Cargo to pass `--cap-lints allow` to all upstream
dependencies instead of `-A warings`. This should serve the same purpose of
suppressing warnings in upstream dependencies as well as preventing widespread
breakage whenever a change to a lint is introduced in the compiler.

src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/custom_build.rs
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/ops/mod.rs
src/cargo/util/config.rs
src/cargo/util/mod.rs
src/cargo/util/rustc.rs [new file with mode: 0644]
tests/test_cargo_compile_git_deps.rs
tests/tests.rs

index a927208042b2368fd8579f49fbd9bb1aa3ba0ced..9502d94443163ae51c5cb33e2fb16d39139d4959 100644 (file)
@@ -126,7 +126,6 @@ pub fn compile_pkg<'a>(package: &Package,
     let override_ids = try!(source_ids_from_config(config, package.root()));
 
     let (packages, resolve_with_overrides, sources) = {
-        let rustc_host = config.rustc_host().to_string();
         let mut registry = PackageRegistry::new(config);
         if let Some(source) = source {
             registry.preload(package.package_id().source_id(), source);
@@ -146,13 +145,14 @@ pub fn compile_pkg<'a>(package: &Package,
 
         try!(registry.add_overrides(override_ids));
 
-        let platform = target.as_ref().map(|e| &e[..]).or(Some(&rustc_host[..]));
+        let platform = target.as_ref().unwrap_or(&config.rustc_info().host);
 
-        let method = Method::Required{
+        let method = Method::Required {
             dev_deps: true, // TODO: remove this option?
             features: &features,
             uses_default_features: !no_default_features,
-            target_platform: platform};
+            target_platform: Some(&platform[..]),
+        };
 
         let resolved_with_overrides =
                 try!(ops::resolve_with_previous(&mut registry, package, method,
@@ -397,7 +397,7 @@ fn scrape_build_config(config: &Config,
         requested_target: target.clone(),
         ..Default::default()
     };
-    base.host = try!(scrape_target_config(config, config.rustc_host()));
+    base.host = try!(scrape_target_config(config, &config.rustc_info().host));
     base.target = match target.as_ref() {
         Some(triple) => try!(scrape_target_config(config, &triple)),
         None => base.host.clone(),
index 2782213ddf32de1ee50cbd36ae8373e9ef553160..93eecb742782a0204e32203f0d7c63a613811b65 100644 (file)
@@ -70,7 +70,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         } else {
             try!(Context::filename_parts(None, config))
         };
-        let target_triple = target.unwrap_or(config.rustc_host()).to_string();
+        let target_triple = target.unwrap_or_else(|| {
+            &config.rustc_info().host[..]
+        }).to_string();
         let engine = build_config.exec_engine.as_ref().cloned().unwrap_or({
             Arc::new(Box::new(ProcessEngine))
         });
@@ -244,9 +246,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     /// otherwise it corresponds to the target platform.
     fn dylib(&self, kind: Kind) -> CargoResult<(&str, &str)> {
         let (triple, pair) = if kind == Kind::Host {
-            (self.config.rustc_host(), &self.host_dylib)
+            (&self.config.rustc_info().host, &self.host_dylib)
         } else {
-            (&self.target_triple[..], &self.target_dylib)
+            (&self.target_triple, &self.target_dylib)
         };
         match *pair {
             None => return Err(human(format!("dylib outputs are not supported \
index b2c98a41b724e723423450d97e739b1c90858091..0c939dd5923eaf23dceb2232d4e6eb51cb75fc43 100644 (file)
@@ -63,13 +63,13 @@ pub fn prepare(pkg: &Package, target: &Target, req: Platform,
      .env("CARGO_MANIFEST_DIR", pkg.root())
      .env("NUM_JOBS", &cx.jobs().to_string())
      .env("TARGET", &match kind {
-         Kind::Host => cx.config.rustc_host(),
+         Kind::Host => &cx.config.rustc_info().host[..],
          Kind::Target => cx.target_triple(),
      })
      .env("DEBUG", &profile.debuginfo.to_string())
      .env("OPT_LEVEL", &profile.opt_level.to_string())
      .env("PROFILE", if cx.build_config.release {"release"} else {"debug"})
-     .env("HOST", &cx.config.rustc_host());
+     .env("HOST", &cx.config.rustc_info().host);
 
     // Be sure to pass along all enabled features for this package, this is the
     // last piece of statically known information that we have.
index b72931d19bb75784c95600dae3ed1dd874156d99..05336eebff8ff21342202188397d0c218067f22a 100644 (file)
@@ -165,8 +165,8 @@ fn calculate<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
         v.sort();
         v
     });
-    let extra = util::short_hash(&(cx.config.rustc_version(), target, &features,
-                                   profile));
+    let extra = util::short_hash(&(&cx.config.rustc_info().verbose_version,
+                                   target, &features, profile));
     debug!("extra {:?} {:?} {:?} = {}", target, profile, features, extra);
 
     // Next, recursively calculate the fingerprint for all of our dependencies.
index 486ce8d5c899c8ed0b4a4040926adadba5e56f6a..aac936656a5b2e2b0ec596c004704eb6d9b53dc7 100644 (file)
@@ -3,7 +3,7 @@ use std::env;
 use std::ffi::OsString;
 use std::fs;
 use std::io::prelude::*;
-use std::path::{self, Path, PathBuf};
+use std::path::{self, PathBuf};
 use std::sync::Arc;
 
 use core::{SourceMap, Package, PackageId, PackageSet, Target, Resolve};
@@ -52,29 +52,6 @@ pub struct TargetConfig {
     pub overrides: HashMap<String, BuildOutput>,
 }
 
-/// Run `rustc` to figure out what its current version string is.
-///
-/// The second element of the tuple returned is the target triple that rustc
-/// is a host for.
-pub fn rustc_version<P: AsRef<Path>>(rustc: P) -> CargoResult<(String, String)> {
-    let output = try!(try!(util::process(rustc.as_ref()))
-        .arg("-vV")
-        .exec_with_output());
-    let output = try!(String::from_utf8(output.stdout).map_err(|_| {
-        internal("rustc -v didn't return utf8 output")
-    }));
-    let triple = {
-        let triple = output.lines().filter(|l| {
-            l.starts_with("host: ")
-        }).map(|l| &l[6..]).next();
-        let triple = try!(triple.chain_error(|| {
-            internal("rustc -v didn't have a line for `host:`")
-        }));
-        triple.to_string()
-    };
-    Ok((output, triple))
-}
-
 // Returns a mapping of the root package plus its immediate dependencies to
 // where the compiled libraries are all located.
 pub fn compile_targets<'a, 'cfg: 'a>(targets: &[(&'a Target, &'a Profile)],
@@ -336,10 +313,14 @@ fn rustc(package: &Package, target: &Target, profile: &Profile,
     return rustcs.into_iter().map(|(mut rustc, kind)| {
         let name = package.name().to_string();
         let is_path_source = package.package_id().source_id().is_path();
-        let show_warnings = package.package_id() == cx.resolve.root() ||
-                            is_path_source;
-        if !show_warnings {
-            rustc.arg("-Awarnings");
+        let allow_warnings = package.package_id() == cx.resolve.root() ||
+                             is_path_source;
+        if !allow_warnings {
+            if cx.config.rustc_info().cap_lints {
+                rustc.arg("--cap-lints").arg("allow");
+            } else {
+                rustc.arg("-Awarnings");
+            }
         }
         let has_custom_args = profile.rustc_args.is_some();
         let exec_engine = cx.exec_engine.clone();
index 24106aa7a5fa8dbb3e58e38b15fd4437816c05f1..545187a98df95ae243d6d804122eb52f62bfb14c 100644 (file)
@@ -2,7 +2,7 @@ pub use self::cargo_clean::{clean, CleanOptions};
 pub use self::cargo_compile::{compile, compile_pkg, CompileOptions};
 pub use self::cargo_compile::{CompileFilter, CompileMode};
 pub use self::cargo_read_manifest::{read_manifest,read_package,read_packages};
-pub use self::cargo_rustc::{compile_targets, Compilation, Layout, Kind, rustc_version};
+pub use self::cargo_rustc::{compile_targets, Compilation, Layout, Kind};
 pub use self::cargo_rustc::{Context, LayoutProxy};
 pub use self::cargo_rustc::Platform;
 pub use self::cargo_rustc::{BuildOutput, BuildConfig, TargetConfig};
index 90c971e8338d38469459dd51735472d9e8ef2983..a3ccb29eb4cb01212bcaf01c972f32994e442544 100644 (file)
@@ -12,8 +12,7 @@ use std::path::{Path, PathBuf};
 use rustc_serialize::{Encodable,Encoder};
 use toml;
 use core::{MultiShell, Package};
-use ops;
-use util::{CargoResult, ChainError, internal, human};
+use util::{CargoResult, ChainError, Rustc, internal, human};
 
 use util::toml as cargo_toml;
 
@@ -22,9 +21,7 @@ use self::ConfigValue as CV;
 pub struct Config {
     home_path: PathBuf,
     shell: RefCell<MultiShell>,
-    rustc_version: String,
-    /// The current host and default target of rustc
-    rustc_host: String,
+    rustc_info: Rustc,
     values: RefCell<HashMap<String, ConfigValue>>,
     values_loaded: Cell<bool>,
     cwd: PathBuf,
@@ -45,8 +42,7 @@ impl Config {
                       This probably means that $HOME was not set.")
             })),
             shell: RefCell::new(shell),
-            rustc_version: String::new(),
-            rustc_host: String::new(),
+            rustc_info: Rustc::blank(),
             cwd: cwd,
             values: RefCell::new(HashMap::new()),
             values_loaded: Cell::new(false),
@@ -92,11 +88,7 @@ impl Config {
 
     pub fn rustdoc(&self) -> &Path { &self.rustdoc }
 
-    /// Return the output of `rustc -v verbose`
-    pub fn rustc_version(&self) -> &str { &self.rustc_version }
-
-    /// Return the host platform and default target of rustc
-    pub fn rustc_host(&self) -> &str { &self.rustc_host }
+    pub fn rustc_info(&self) -> &Rustc { &self.rustc_info }
 
     pub fn values(&self) -> CargoResult<Ref<HashMap<String, ConfigValue>>> {
         if !self.values_loaded.get() {
@@ -219,9 +211,7 @@ impl Config {
     }
 
     fn scrape_rustc_version(&mut self) -> CargoResult<()> {
-        let (rustc_version, rustc_host) = try!(ops::rustc_version(&self.rustc));
-        self.rustc_version = rustc_version;
-        self.rustc_host = rustc_host;
+        self.rustc_info = try!(Rustc::new(&self.rustc));
         Ok(())
     }
 
index ed4d079f972146665e7a24bf9182631a62eb0955..b47e8095dd4cd0dea4e23d1dd5041a5aad964243 100644 (file)
@@ -1,20 +1,21 @@
 pub use self::config::Config;
-pub use self::process_builder::{process, ProcessBuilder};
+pub use self::dependency_queue::Dependency;
+pub use self::dependency_queue::{DependencyQueue, Fresh, Dirty, Freshness};
 pub use self::errors::{CargoResult, CargoError, ChainError, CliResult};
 pub use self::errors::{CliError, ProcessError};
-pub use self::errors::{process_error, internal_error, internal, human};
 pub use self::errors::{Human, caused_human};
+pub use self::errors::{process_error, internal_error, internal, human};
+pub use self::graph::Graph;
+pub use self::hex::{to_hex, short_hash};
+pub use self::lev_distance::{lev_distance};
 pub use self::paths::{join_paths, path2bytes, bytes2path, dylib_path};
 pub use self::paths::{normalize_path, dylib_path_envvar, without_prefix};
-pub use self::lev_distance::{lev_distance};
-pub use self::hex::{to_hex, short_hash};
-pub use self::dependency_queue::{DependencyQueue, Fresh, Dirty, Freshness};
-pub use self::dependency_queue::Dependency;
-pub use self::graph::Graph;
-pub use self::to_url::ToUrl;
+pub use self::process_builder::{process, ProcessBuilder};
+pub use self::rustc::Rustc;
+pub use self::sha256::Sha256;
 pub use self::to_semver::ToSemver;
+pub use self::to_url::ToUrl;
 pub use self::vcs::{GitRepo, HgRepo};
-pub use self::sha256::Sha256;
 
 pub mod config;
 pub mod errors;
@@ -32,3 +33,4 @@ mod dependency_queue;
 mod sha256;
 mod shell_escape;
 mod vcs;
+mod rustc;
diff --git a/src/cargo/util/rustc.rs b/src/cargo/util/rustc.rs
new file mode 100644 (file)
index 0000000..0a3fbf6
--- /dev/null
@@ -0,0 +1,50 @@
+use std::path::Path;
+
+use util::{self, CargoResult, internal, ChainError};
+
+pub struct Rustc {
+    pub verbose_version: String,
+    pub host: String,
+    pub cap_lints: bool,
+}
+
+impl Rustc {
+    /// Run the compiler at `path` to learn varioues pieces of information about
+    /// it.
+    ///
+    /// If successful this function returns a description of the compiler along
+    /// with a list of its capabilities.
+    pub fn new<P: AsRef<Path>>(path: P) -> CargoResult<Rustc> {
+        let mut cmd = try!(util::process(path.as_ref()));
+        cmd.arg("-vV");
+
+        let mut ret = Rustc::blank();
+        let mut first = cmd.clone();
+        first.arg("--cap-lints").arg("allow");
+        let output = match first.exec_with_output() {
+            Ok(output) => { ret.cap_lints = true; output }
+            Err(..) => try!(cmd.exec_with_output()),
+        };
+        ret.verbose_version = try!(String::from_utf8(output.stdout).map_err(|_| {
+            internal("rustc -v didn't return utf8 output")
+        }));
+        ret.host = {
+            let triple = ret.verbose_version.lines().filter(|l| {
+                l.starts_with("host: ")
+            }).map(|l| &l[6..]).next();
+            let triple = try!(triple.chain_error(|| {
+                internal("rustc -v didn't have a line for `host:`")
+            }));
+            triple.to_string()
+        };
+        Ok(ret)
+    }
+
+    pub fn blank() -> Rustc {
+        Rustc {
+            verbose_version: String::new(),
+            host: String::new(),
+            cap_lints: false,
+        }
+    }
+}
index 91917a390953fc417804f315800c306da2afda89..2f73a2f4e0a70689a622fd945de321dfbaa934b7 100644 (file)
@@ -1654,3 +1654,73 @@ test!(doctest_same_name {
     assert_that(p.cargo_process("test").arg("-v"),
                 execs().with_status(0));
 });
+
+test!(lints_are_suppressed {
+    let a = git::new("a", |p| {
+        p.file("Cargo.toml", r#"
+            [project]
+            name = "a"
+            version = "0.5.0"
+            authors = []
+        "#)
+        .file("src/lib.rs", "
+            use std::option;
+        ")
+    }).unwrap();
+
+    let p = project("foo")
+        .file("Cargo.toml", &format!(r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            a = {{ git = '{}' }}
+        "#, a.url()))
+        .file("src/lib.rs", "");
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(0).with_stdout(&format!("\
+{updating} git repository `[..]`
+{compiling} a v0.5.0 ([..])
+{compiling} foo v0.0.1 ([..])
+", compiling = COMPILING, updating = UPDATING)));
+});
+
+test!(denied_lints_are_allowed {
+    let enabled = super::RUSTC.with(|r| r.cap_lints);
+    if !enabled { return }
+
+    let a = git::new("a", |p| {
+        p.file("Cargo.toml", r#"
+            [project]
+            name = "a"
+            version = "0.5.0"
+            authors = []
+        "#)
+        .file("src/lib.rs", "
+            #![deny(warnings)]
+            use std::option;
+        ")
+    }).unwrap();
+
+    let p = project("foo")
+        .file("Cargo.toml", &format!(r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            a = {{ git = '{}' }}
+        "#, a.url()))
+        .file("src/lib.rs", "");
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(0).with_stdout(&format!("\
+{updating} git repository `[..]`
+{compiling} a v0.5.0 ([..])
+{compiling} foo v0.0.1 ([..])
+", compiling = COMPILING, updating = UPDATING)));
+});
index b82c2ecf5ff85db1111ba36587cae9588622d3e0..43d1c2fd9d6980bb219dbecd73e9ee8a9cc2d10f 100644 (file)
@@ -16,6 +16,8 @@ extern crate url;
 #[macro_use]
 extern crate log;
 
+use cargo::util::Rustc;
+
 mod support;
 macro_rules! test {
     ($name:ident $expr:expr) => (
@@ -57,16 +59,19 @@ mod test_cargo_test;
 mod test_cargo_version;
 mod test_shell;
 
+thread_local!(static RUSTC: Rustc = Rustc::new("rustc").unwrap());
+
 fn rustc_host() -> String {
-    cargo::ops::rustc_version("rustc").unwrap().1
+    RUSTC.with(|r| r.host.clone())
 }
 
 fn is_nightly() -> bool {
-    let version_info = cargo::ops::rustc_version("rustc").unwrap().0;
-    version_info.contains("-nightly") || version_info.contains("-dev")
+    RUSTC.with(|r| {
+        r.verbose_version.contains("-nightly") ||
+            r.verbose_version.contains("-dev")
+    })
 }
 
 fn can_panic() -> bool {
-    let host = cargo::ops::rustc_version("rustc").unwrap().1;
-    !host.contains("msvc")
+    RUSTC.with(|r| !r.host.contains("msvc"))
 }